package com.sinosoft.brokerchannel.base.filters;

import com.fasterxml.jackson.annotation.JsonFilter;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.BeanPropertyFilter;
import com.fasterxml.jackson.databind.ser.FilterProvider;
import com.fasterxml.jackson.databind.ser.PropertyFilter;
import com.fasterxml.jackson.databind.ser.PropertyWriter;
import com.fasterxml.jackson.databind.ser.impl.SimpleBeanPropertyFilter;

import java.util.*;

/**
 * @类描述:json过滤器
 */
@SuppressWarnings("deprecation")
@JsonFilter("JacksonFilter")
public class JacksonFilter extends FilterProvider {
    /**
     * 类中需要包含的字段与该类的映射
     */
    private final Map<Class<?>, Set<String>> includeMap = new HashMap<>();
    /**
     * 类中需要过滤掉的字段与该类的映射
     */
    private final Map<Class<?>, Set<String>> filterMap = new HashMap<>();

    /**
     * @param type   某个类
     * @param fields 包含的字段
     * @方法描述:类中需要包含的字段
     * @参数说明：
     */
    public void include(Class<?> type, String[] fields) {
        addToMap(includeMap, type, fields);
    }

    /**
     * @param type   某个类
     * @param fields 过滤掉的字段
     * @方法描述:类中需要过滤出来的字段
     * @参数说明：
     */
    public void filter(Class<?> type, String[] fields) {
        addToMap(filterMap, type, fields);
    }

    /**
     * @param map    映射集合
     * @param type   类
     * @param fields 过滤字段
     * @方法描述:创建类和该类要过滤的字段的映射
     * @参数说明：
     */
    private void addToMap(Map<Class<?>, Set<String>> map, Class<?> type, String[] fields) {
        Set<String> fieldSet = map.getOrDefault(type, new HashSet<>());
        fieldSet.addAll(Arrays.asList(fields));
        map.put(type, fieldSet);
    }

    @Override
    public BeanPropertyFilter findFilter(Object filterId) {
        return null;
    }

    @Override
    public PropertyFilter findPropertyFilter(Object filterId, Object valueToFilter) {
        return new SimpleBeanPropertyFilter() {

            @Override
            public void serializeAsField(Object pojo, JsonGenerator jgen, SerializerProvider prov, PropertyWriter writer) throws Exception {
                if (apply(pojo.getClass(), writer.getName())) {
                    writer.serializeAsField(pojo, jgen, prov);
                } else if (!jgen.canOmitFields()) {
                    writer.serializeAsOmittedField(pojo, jgen, prov);
                }
            }
        };
    }

    private boolean apply(Class<?> type, String name) {
        return includeMap.get(type) != null && includeMap.get(type).contains(name);
    }
}
